﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
using Jayden.Dll.Core.Enums;
using Jayden.Dll.Core.Persistence;
using Jayden.Dll.Core.Persistence.Attributes;
using Jayden.Dll.Core.Persistence.Enums;
using Jayden.Dll.Core.Persistence.Models;

namespace Jayden.Dll.Core.Membership
{
	[Table]
	public class User : System.Web.Security.MembershipUser, Jayden.Dll.Core.Persistence.Object
	{
		private Entity m_Entity;

		private ObjectId m_ObjectId;
		private UnitOfWork m_UnitOfWork;
		private ObjectState m_State;

		private DateTime? m_CreationDate = null;
		private bool? m_IsLockedOut = null;
		private DateTime? m_LastLockoutDate = null;
		private DateTime? m_LastPasswordChangedDate = null;
		private string m_PasswordQuestion = null;
		private string m_UserName = null;

		private bool m_IsEmailValidated = false;
		private string m_CultureCode = null;
		private string m_Avatar = null;
		private Gender m_Gender = Gender.Unknow;
		private string m_FirstName;
		private string m_LastName;
		private DateTime m_BirthDate; 

		private string m_Password = null;
		private string m_PasswordAnswer = null;
		private string m_Guid = System.Guid.NewGuid().ToString("N");

		private string m_XmlData = null;
		private XmlDocument m_XmlDocument = null;

		public User(UnitOfWork uow, string providerName, string name, long memberId, string email, string passwordQuestion, string comment, bool isApproved, bool isLockedOut, System.DateTime creationDate, System.DateTime lastLoginDate, System.DateTime lastActivityDate, System.DateTime lastPasswordChangedDate, System.DateTime lastLockoutDate)
			: base(providerName, name, memberId, email, passwordQuestion, comment, isApproved, isLockedOut, creationDate, lastLoginDate, lastActivityDate, lastPasswordChangedDate, lastLockoutDate)
		{
			m_UnitOfWork = uow;
			m_ObjectId = new ObjectId(Entity.ObjectType, memberId);
			m_State = ObjectState.New;
		}

		public virtual string EntityFullName { get { return GetType().FullName; } }
		public Entity Entity
		{
			get
			{
				if (m_Entity == null)
					m_Entity = m_UnitOfWork.Model.GetEntity(EntityFullName);
				return m_Entity;
			}
		}

		public UnitOfWork UnitOfWork { get { return m_UnitOfWork; } }
		public ObjectType Type { get { return Entity.ObjectType; } }
		public ObjectId ObjectId { get { return m_ObjectId; } }
		public ObjectState State { get { return m_State; } set { m_State = value; } }

		public string UserDirectory { get { return string.Format("/Users/{0}/", UserName); } }

		[Field(PrimaryKey=true, AutoIncrement=true)]
		public long MemberId { get { return (long)ObjectId[0]; } set { ObjectId[0] = value; } }

		[Field(Nullable=true)]
		public override string Comment
		{
			get { return base.Comment; }
			set
			{
				base.Comment = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field(Unique=true)]
		public override string Email
		{
			get { return base.Email; }
			set
			{
				base.Email = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field]
		public string XmlData
		{
			get { return m_XmlData; }
			set
			{
				m_XmlData = value;
				m_XmlDocument = null;
				m_State = ObjectState.Dirty;
			}
		}

		public XmlDocument XmlDocument
		{
			get
			{
				if (m_XmlData == null)
					return null;
				if (m_XmlDocument != null)
					return m_XmlDocument;
				try
				{
					m_XmlDocument = new XmlDocument();
					m_XmlDocument.LoadXml(m_XmlData);
					return m_XmlDocument;
				}
				catch
				{
				}
				return null;
			}
		}

		[Field]
		public new DateTime CreationDate
		{
			get
			{
				if (m_CreationDate.HasValue)
					return m_CreationDate.Value;
				return base.CreationDate;
			}
			set
			{
				m_CreationDate = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field(DefaultValue=true)]
		public override bool IsApproved
		{
			get { return base.IsApproved; }
			set
			{
				base.IsApproved = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field(DefaultValue = false)]
		public bool IsEmailValidated
		{
			get { return m_IsEmailValidated; }
			set
			{
				m_IsEmailValidated = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field(DefaultValue=false)]
		public new bool IsLockedOut
		{
			get
			{
				if (m_IsLockedOut.HasValue)
					return m_IsLockedOut.Value;
				return base.IsLockedOut;
			}
			set
			{
				m_IsLockedOut = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field]
		public override System.DateTime LastActivityDate
		{
			get { return base.LastActivityDate; }
			set
			{
				base.LastActivityDate = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field]
		public new DateTime LastLockoutDate
		{
			get
			{
				if (m_LastLockoutDate.HasValue)
					return m_LastLockoutDate.Value;
				return base.LastLockoutDate;
			}
			set
			{
				m_LastLockoutDate = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field]
		public override System.DateTime LastLoginDate
		{
			get { return base.LastLoginDate; }
			set
			{
				base.LastLoginDate = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field]
		public new DateTime LastPasswordChangedDate
		{
			get
			{
				if (m_LastPasswordChangedDate.HasValue)
					return m_LastPasswordChangedDate.Value;
				return base.LastPasswordChangedDate;
			}
			set
			{
				m_LastPasswordChangedDate = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field(Nullable = true)]
		public string Avatar
		{
			get { return m_Avatar; }
			set
			{
				m_Avatar = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field(Nullable = true)]
		public string Guid
		{
			get { return m_Guid; }
			set
			{
				m_Guid = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field(Nullable=true)]
		public new string PasswordQuestion
		{
			get
			{
				if (m_PasswordQuestion != null)
					return m_PasswordQuestion;
				return base.PasswordQuestion;
			}
			set
			{
				m_PasswordQuestion = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field(Unique=true)]
		public new string UserName
		{
			get
			{
				if (m_UserName != null)
					return m_UserName;
				return base.UserName;
			}
			set
			{
				m_UserName = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field]
		public string Password
		{
			get { return m_Password; }
			set
			{
				m_Password = value;
				m_State = ObjectState.Dirty;
			}
		}

		[Field(Nullable = true)]
		public string PasswordAnswer
		{
			get { return m_PasswordAnswer; }
			set
			{
				m_PasswordAnswer = value;
				m_State = ObjectState.Dirty;
			}
		}
		[Field(DefaultValue=Gender.Unknow)]
		public Gender Gender { get { return m_Gender; } set { m_Gender = value; } }
		[Field(Nullable=true)]
		public string FirstName { get { return m_FirstName; } set { m_FirstName = value; } }
		[Field(Nullable=true)]
		public string LastName { get { return m_LastName; } set { m_LastName = value; } }
		[Field]
		public DateTime BirthDate { get { return m_BirthDate; } set { m_BirthDate = value; } }
		[Field(Nullable=true)]
		public string CultureCode { get { return m_CultureCode; } set { m_CultureCode = value; } }

		private CultureInfo m_CultureInfo;
		public CultureInfo CultureInfo
		{
			get
			{
				if (m_CultureInfo == null && m_CultureCode != null)
					m_CultureInfo = new CultureInfo(m_CultureCode);
				else
					return CultureInfo.InvariantCulture;
				return m_CultureInfo;
			}
		}

		private HashSet<string> m_RoleNames;
		public HashSet<string> RoleNames
		{
			get
			{
				if (m_RoleNames == null)
				{
					m_RoleNames = new HashSet<string>();
					foreach (string rolename in System.Web.Security.Roles.GetRolesForUser(UserName))
						m_RoleNames.Add(rolename);
				}
				return m_RoleNames;
			}
		}
	}
}
